package cn.ven.config;

import cn.ven.entity.MyUser;
import cn.ven.service.UserService;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.*;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

@Configuration
@EnableWebSecurity  //开启过滤器
public class MySecConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    UserService userService;

    @Autowired
    PassConfig passConfig;

    @Autowired
    ObjectMapper objectMapper;


    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(new UserDetailsService() {
            @Override
            public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
                System.out.println("username="+username);
                //获取数据库的user对象
               MyUser user = userService.findByUsername(username);
                System.out.println("user===="+user);
                String password = passConfig.passwordEncoder().encode(user.getPassword());
                System.out.println("password===="+password);
                user.setPassword(password);
                return user;
            }
        });
    }


    //放行静态资源
    @Override
    public void configure(WebSecurity web) throws Exception {
//        web.ignoring().antMatchers("/css/**");
//        web.ignoring().antMatchers("/js/**");
//        web.ignoring().antMatchers("/img/**");
        web.ignoring().antMatchers("/static/**");
        web.ignoring().antMatchers("/js/**");
        web.ignoring().antMatchers("/el/**");
        web.ignoring().antMatchers("/login/**");
        //解决服务器注册url被拦截问题
        web.ignoring().antMatchers("/resources/**");
    }

    //http安全请求处理
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http .authorizeRequests()  //所有游览器请求
                .antMatchers("/api/user/**").permitAll()
                .antMatchers("/api/public/**").permitAll()
                .antMatchers("/api/fore/**").hasAuthority("B")
                .anyRequest().authenticated().
                and().
                formLogin().loginPage("/api/public/go2Login")
                .loginProcessingUrl("/doLogin")
                .successHandler(new AuthenticationSuccessHandler() {
                    @Override
                    public void onAuthenticationSuccess(HttpServletRequest request,
                                                        HttpServletResponse response,
                                                        Authentication authentication) throws IOException, ServletException {
                        System.out.println("登陆成功======"+authentication);
                        Object principal = authentication.getPrincipal();
                        System.out.println("principal===="+principal);
                        System.out.println("登录成功 .Authorities。=="+authentication.getAuthorities());
                        Collection<?extends GrantedAuthority> authorities =authentication.getAuthorities();

                        response.setContentType("application/json;charset=utf-8");
                        PrintWriter out =response.getWriter();
                        response.setStatus(200);
                        Map<String,Object> map =new HashMap<>();
                        map.put("status",200);
                        map.put("code",0);
                        map.put("data",principal);
                        map.put("msg","登陆成功");

                        for (GrantedAuthority authority:authorities){
                            System.out.println("authority.getAuthority()=" + authority.getAuthority());
                            if (authority.getAuthority().contains("B")){
                                map.put("action","/api/public/go2Index");
                            }
                            if (authority.getAuthority().contains("A")){
                                map.put("action","/api/public/go2Index");
                            }
                          else {
                                map.put("action","/api/public/go2Login");
                            }
                        }
                        String strJson = objectMapper.writeValueAsString(map);
                        out.write(strJson);
                        out.flush();
                        out.close();
                    }
                })  //登陆成功
                .failureHandler(new AuthenticationFailureHandler() {
                    @Override
                    public void onAuthenticationFailure(HttpServletRequest request,
                                                        HttpServletResponse response,
                                                        AuthenticationException exception) throws IOException, ServletException {
                        System.out.println("登录失败 .....");
                        response.setContentType("application/json;charset=utf-8");
                        PrintWriter out = response.getWriter();
                        response.setStatus(200);
                        Map<String, Object> map = new HashMap<>();
                        map.put("status", 401);
                        map.put("code", -1);
                        if (exception instanceof LockedException){
                            map.put("msg","账户密码锁定，登录失败！");
                        }else if (exception instanceof BadCredentialsException){
                            map.put("msg","账户名或密码输入错误，登录失败！");
                        }else if(exception instanceof DisabledException){
                            map.put("msg","账户被禁用，登录失败！");
                        }else if (exception instanceof AccountExpiredException){
                            map.put("msg","账户已过期，登录失败！");
                        }else if (exception instanceof CredentialsExpiredException){
                            map.put("msg","密码已过期，登录失败！");
                        }else {
                            map.put("msg","登录失败！");
                        }
                        String strJson = objectMapper.writeValueAsString(map);
                        out.write(strJson);
                        out.flush();
                        out.close();
                    }
                })
                .permitAll()
                .and()
                .logout()                   //开启注销登陆
                .logoutUrl("/logout")        //注销登陆请求url
                .clearAuthentication(true)    //清除身份信息
                .invalidateHttpSession(true)   //session失效
                .addLogoutHandler(new LogoutHandler() { //注销处理
                    @Override
                    public void logout(HttpServletRequest req,
                                       HttpServletResponse resp,
                                       Authentication auth) {

                    }
                })
                .logoutSuccessHandler(new LogoutSuccessHandler() {     //注销成功处理
                    @Override
                    public void onLogoutSuccess(HttpServletRequest req,
                                                HttpServletResponse resp,
                                                Authentication auth)
                            throws IOException {
                        System.out.println("注销成功");
                        resp.sendRedirect("/api/public/go2Login");//跳转到自定义登陆页面
                    }
                })
                .and().csrf().disable();//需要登录后才能访问


    }



}
